package com.mayikt.template.impl;

import com.alipay.api.internal.util.AlipaySignature;
import com.mayikt.config.AlipayConfig;
import com.mayikt.entity.PaymentChannelEntity;
import com.mayikt.entity.PaymentTransactionEntity;
import com.mayikt.mapper.PaymentTransactionMapper;
import com.mayikt.template.AbstractPayCallbackTemplate;
import com.mayikt.template.PayThreadInfoHolder;
import com.mayikt.utils.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component
@Slf4j
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Autowired
    private PayThreadInfoHolder payThreadInfoHolder;


    @Override
    protected String getPayOrderNo() {
        // 1. 根据支付订单号码查询数据库 ，是否已经支付过
        Map<String, String> requestParams = currentRequestParams();
        // 支付订单号码
        String outTradeNo = requestParams.get("out_trade_no");
        return outTradeNo;
    }

    @Override
    protected Long getTotalAmount() {
        // 1. 根据支付订单号码查询数据库 ，是否已经支付过
        Map<String, String> requestParams = currentRequestParams();
        String totalAmount = requestParams.get("total_amount");
        Long aliPayAmount = yuanToFen(totalAmount);
        return aliPayAmount;
    }

    @Override
    protected String resultFail() {
        return "fail";
    }

    @Override
    protected String resultSuccess() {
        return "success";
    }

    @Override
    protected boolean verifySignature(PaymentChannelEntity pce) {
        // 根据当前线程获取Request
        HttpServletRequest request = ServletUtils.getCurrentRequest();
        HttpServletResponse response = ServletUtils.getCurrentResponse();
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                //乱码解决，这段代码在出现乱码时使用
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
                // 防止验证签名失败
                params.remove("channelId");
            }
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params, pce.getPublicKey(), AlipayConfig.CHARSET, AlipayConfig.SIGN_TYPE); //调用SDK验证签名
            if (signVerified) {
                out.println("success");
                return true;
            } else {
                //验证失败
                return false;
            }
        } catch (Exception e) {
            log.error("verifySignature()>> errorMsg:" + e.getMessage());
            return false;
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {

            }
            payThreadInfoHolder.setRequestParams(params);
        }
    }

    private static Long yuanToFen(String amount) {
        NumberFormat format = NumberFormat.getInstance();
        try {
            Number number = format.parse(amount);
            double temp = number.doubleValue() * 100.0;
            format.setGroupingUsed(false);
            // 设置返回数的小数部分所允许的最大位数
            format.setMaximumFractionDigits(0);
            amount = format.format(temp);
            return Long.parseLong(amount);
        } catch (ParseException e) {
            return null;
        }

    }
}
